package routers

import (
	"encoding/json"
	"gf-assistant/internal/common"
	"gf-assistant/internal/common/consts"
	"gf-assistant/internal/common/encrypt"
	"gf-assistant/internal/common/factory"
	"github.com/gogf/gf/v2/util/gconv"
	"net/http"
	"reflect"
	"strings"

	"github.com/gogf/gf/v2/container/garray"
	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/gogf/gf/v2/os/gctx"
)

type Middleware struct{}

const MIDDLEWARE_NAME = "routers.Middleware"

func init() {
	middleware := Middleware{}
	factory.Put(reflect.TypeOf(middleware).String(), &middleware)
}

func GetMiddleware() *Middleware {
	return factory.Get(MIDDLEWARE_NAME).(*Middleware)
}
func (s *Middleware) ResponseHandler(r *ghttp.Request) {
	g.Log("requestLogger").SetAsync(true)
	g.Log("requestLogger").Info(gctx.New(), "URL "+r.RequestURI+", METHOD "+r.Method+", host "+r.Host+", params"+r.GetBodyString())
	r.Middleware.Next()
	// 如果已经有返回内容，那么该中间件什么也不做
	if r.Response.BufferLength() > 0 {
		Status := r.Response.Status
		String := r.Response.Buffer()
		Msg := strings.ReplaceAll(string(String), "exception recovered: ", "")
		r.Response.ClearBuffer()
		if Status != http.StatusUnauthorized && Status != http.StatusOK {
			g.Log("requestLogger").Error(gctx.New(), "error:URL "+r.RequestURI+", METHOD "+r.Method+", host "+r.Host+", params"+r.GetBodyString())
		}
		if Status == http.StatusOK {
			res := common.BaseResponse{}
			err := json.Unmarshal(String, &res)
			if err != nil {
				return
			}
			Status = res.Status
			Msg = res.Msg
		}

		common.JsonExit(r, Status, Msg, gconv.Uint(0))
		return
	}
	var (
		err             = r.GetError()
		res             = r.GetHandlerResponse()
		code gcode.Code = gcode.CodeOK
	)
	if err != nil {
		code = gerror.Code(err)
		if code == gcode.CodeNil {
			code = gcode.CodeInternalError
		}
		common.JsonExit(r, code.Code(), err.Error(), gconv.Uint(0))
	}
	// 返回数据进行加密
	token := r.GetHeader("Token")
	if token == "undefined" {
		token = ""
	}
	aesEncrypt := encrypt.NewAesEncrypt(token)
	//encrypt.NewBuilder(aesEncrypt).Build()
	//resJson, _ := json.Marshal(res)
	//encryptData, _ := gaes.EncryptCBC([]byte(string(resJson)), []byte(aesEncrypt.Key), []byte(aesEncrypt.IV))
	//common.JsonExit(r, code.Code(), "", aesEncrypt.Level, encryptData)
	common.JsonExit(r, code.Code(), "", aesEncrypt.Level, &res)
}
func (s *Middleware) Auth(r *ghttp.Request) {
	var path = garray.NewStrArray()
	path.SetArray(g.SliceStr{"/login"})
	if path.Contains(r.RequestURI) == true {
		r.Middleware.Next()
		return
	}
	token := r.GetHeader("Token")
	r.SetParam("token", token)
	if token == "" {
		r.Response.WriteStatus(http.StatusUnauthorized, "请先登录")
		return
	}
	redisKey := consts.RedisKeyUserToken + ":" + token
	res, err := g.Redis().Get(r.Context(), redisKey)
	if err != nil || g.IsEmpty(res) {
		r.Response.WriteStatus(http.StatusUnauthorized, "请先登录")
		return
	}

	r.SetCtxVar(consts.ContextKeyUserId, res.Uint()) //将userId设置到context中
	r.Middleware.Next()
}
func (s *Middleware) Ctx(r *ghttp.Request) {
	r.SetCtxVar(consts.ContextKeyToken, r.Header.Get("Token")) //将token设置到context中
	// 执行下一步请求逻辑
	r.Middleware.Next()
}
